<?php

namespace SunAdmin;

use SunAdmin\Exception\ExceptionHandle;
use think\Service;
use think\facade\Route;
use think\facade\Db;
use think\facade\Cache;
use think\swoole\Manager;

class SunAdminService extends Service
{
    /**
     * 注册服务
     */
    public function register()
    {
        $manage = $this->app->make(Manager::class);
        if($manage->getWorkerId() === 0){
            //检测ws是否启用
            $this->checkWsEnabled();
            // 检测 Swoole 环境
            $this->checkSwooleEnvironment();
            // 检测数据库连接
            $this->checkDatabaseConnection();
            // 检测缓存驱动必须为 redis
            $this->checkCacheDriver();
        }

        // 注册配置
        $this->app->config->load(__DIR__ . '/../config/sunadmin.php', 'sunadmin');
        // 注册路由
        $this->app->event->listen(\think\event\RouteLoaded::class, function () {
            if (file_exists(__DIR__ . '/../routes/sunadmin.php')) {
                include __DIR__ . '/../routes/sunadmin.php';
            }
        });
        // 注册中间件
        $this->app->middleware->add(\SunAdmin\Middleware\AllowCrossDomain::class);
        // 注册事件订阅
        $this->app->event->subscribe(\SunAdmin\Subscribe\SystemEventSubscribe::class);
        // 异常接管
        $this->app->bind('think\exception\Handle',ExceptionHandle::class);
    }

    /**
     * 启动服务
     */
    public function boot()
    {

    }

    /**
     * 检测 Swoole 环境
     */
    private function checkSwooleEnvironment()
    {
        // 检查是否安装了 Swoole 扩展
        if (!extension_loaded('swoole')) {
            $this->showSwooleError('Swoole 扩展未安装');
            return;
        }

        // 检查是否在 Swoole 环境下运行
        if (!$this->isSwooleRunning()) {
            $this->showSwooleWarning();
        }
    }

    /**
     * 检测是否在 Swoole 环境下运行
     */
    private function isSwooleRunning(): bool
    {
        // 检查是否存在 Swoole 相关的全局变量或常量
        if (defined('SWOOLE_VERSION')) {
            return true;
        }

        // 检查是否在 Swoole Server 环境中
        if (class_exists('\Swoole\Server') && isset($GLOBALS['swoole_server'])) {
            return true;
        }

        // 检查 SAPI 类型
        if (php_sapi_name() === 'cli' && isset($_SERVER['argv'])) {
            $argv = $_SERVER['argv'];
            // 检查命令行参数中是否包含 swoole 相关命令
            foreach ($argv as $arg) {
                if (strpos($arg, 'swoole') !== false) {
                    return true;
                }
            }
        }

        // 检查环境变量
        if (getenv('SWOOLE_HTTP_SERVER') || getenv('THINK_SWOOLE')) {
            return true;
        }

        return false;
    }

    /**
     * 显示 Swoole 错误信息
     */
    private function showSwooleError(string $message)
    {
        $error = "\n" . str_repeat('=', 80) . "\n";
        $error .= "❌ SunAdmin 致命错误\n";
        $error .= str_repeat('=', 80) . "\n";
        $error .= "错误信息: {$message}\n\n";
        $error .= "SunAdmin 需要 Swoole 扩展支持，请先安装 Swoole：\n";
        $error .= "1. 使用 PECL 安装: pecl install swoole\n";
        $error .= "2. 或使用包管理器安装 (如: apt-get install php-swoole)\n";
        $error .= "3. 安装完成后重启 PHP 服务\n";
        $error .= str_repeat('=', 80) . "\n\n";
        
        if (php_sapi_name() === 'cli') {
            echo $error;
        } else {
            error_log($error);
        }
        
        throw new \RuntimeException("SunAdmin 需要 Swoole 扩展支持");
    }

    /**
     * 显示 Swoole 运行环境警告
     */
    private function showSwooleWarning()
    {
        $warning = "\n" . str_repeat('⚠', 40) . "\n";
        $warning .= "⚠️  SunAdmin 重要提示\n";
        $warning .= str_repeat('⚠', 40) . "\n";
        $warning .= "检测到您可能没有使用 Swoole 方式启动 ThinkPHP 8！\n\n";
        $warning .= "SunAdmin 强烈依赖 Swoole 环境，必须使用以下方式启动：\n";
        $warning .= "✅ 正确启动方式: php think swoole\n";
        $warning .= "❌ 错误启动方式: 传统的 PHP-FPM 或 Apache mod_php\n\n";
        $warning .= "如果您已经在 Swoole 环境下运行，请忽略此警告。\n";
        $warning .= "否则请立即切换到 Swoole 模式，以确保所有功能正常工作！\n\n";
        $warning .= "相关文档: https://www.kancloud.cn/manual/think-swoole\n";
        $warning .= str_repeat('⚠', 40) . "\n\n";
        
        if (php_sapi_name() === 'cli') {
            echo $warning;
        } else {
            error_log($warning);
        }
    }

    /**
     * 检测数据库连接是否正常
     */
    private function checkDatabaseConnection(): void
    {
        try {
            // 使用框架默认连接执行简单查询
            \think\facade\Db::query('SELECT 1');
        } catch (\Throwable $e) {
            $this->showDatabaseError($e->getMessage());
        }
    }

    /**
     * 确保缓存驱动为 redis
     */
    private function checkCacheDriver(): void
    {
        $defaultDriver = config('cache.default');
        if (strtolower((string)$defaultDriver) !== 'redis') {
            $this->showCacheDriverError($defaultDriver);
            return; // 已抛异常，这里只是防御性 return
        }

        // 测试 Redis 连接
        try {
            $testKey = '__sunadmin_redis_check__';
            $testVal = (string)microtime(true);
            Cache::set($testKey, $testVal, 5);
            $val = Cache::get($testKey);
            if ($val != $testVal) {
                throw new \RuntimeException('Redis 读写验证失败');
            }
            // 删除测试键
            Cache::delete($testKey);
        } catch (\Throwable $e) {
            $this->showRedisConnectionError($e->getMessage());
        }
    }
    /**
     * 显示数据库连接错误信息并终止
     */
    private function showDatabaseError(string $message): void
    {
        $error = "\n" . str_repeat('=', 80) . "\n";
        $error .= "❌ SunAdmin 数据库连接失败\n";
        $error .= str_repeat('=', 80) . "\n";
        $error .= "错误信息: {$message}\n\n";
        $error .= "请检查以下内容:\n";
        $error .= "1. 数据库服务是否已启动\n";
        $error .= "2. .env 或 config/database.php 中的连接配置是否正确\n";
        $error .= str_repeat('=', 80) . "\n\n";

        if (php_sapi_name() === 'cli') {
            echo $error;
        } else {
            error_log($error);
        }
        throw new \RuntimeException('数据库连接失败');
    }

    /**
     * 显示缓存驱动错误信息并终止
     */
    private function showCacheDriverError(string $driver): void
    {
        $error = "\n" . str_repeat('=', 80) . "\n";
        $error .= "❌ SunAdmin 缓存驱动错误\n";
        $error .= str_repeat('=', 80) . "\n";
        $error .= "检测到当前默认缓存驱动为: {$driver}\n";
        $error .= "SunAdmin 仅支持 redis 作为缓存驱动。\n\n";
        $error .= "请在 config/cache.php 或 .env 中将缓存驱动设置为 redis，例如：\n";
        $error .= "CACHE_DRIVER=redis\n";
        $error .= str_repeat('=', 80) . "\n\n";

        if (php_sapi_name() === 'cli') {
            echo $error;
        } else {
            error_log($error);
        }
        throw new \RuntimeException('缓存驱动必须为 redis');
    }

    /**
     * 显示 Redis 连接错误信息并终止
     */
    private function showRedisConnectionError(string $message): void
    {
        $error = "\n" . str_repeat('=', 80) . "\n";
        $error .= "❌ SunAdmin Redis 连接失败\n";
        $error .= str_repeat('=', 80) . "\n";
        $error .= "错误信息: {$message}\n\n";
        $error .= "请检查以下内容:\n";
        $error .= "1. Redis 服务是否已启动并监听正确端口\n";
        $error .= "2. config/cache.php 或 .env 中的 Redis 连接配置是否正确\n";
        $error .= str_repeat('=', 80) . "\n\n";

        if (php_sapi_name() === 'cli') {
            echo $error;
        } else {
            error_log($error);
        }
        throw new \RuntimeException('Redis 连接失败');
    }

    /**
     * 检测ws是否启用
     */
    private function checkWsEnabled(): void
    {
        $wsEnabled = config('swoole.websocket.enable');
        if (!$wsEnabled) {
            $error = "\n" . str_repeat('=', 80) . "\n";
            $error .= "❌ SunAdmin WebSocket 未启用\n";
            $error .= str_repeat('=', 80) . "\n";
            $error .= "错误信息: swoole.php 中的 websocket 配置未启用\n\n";
            $error .= "请检查以下内容:\n";
            $error .= "1. swoole.php 中的 websocket 配置是否正确\n";
            $error .= "2. 是否在swoole.php 中配置了 websocket 路由\n";
            $error .= str_repeat('=', 80) . "\n\n";
            if (php_sapi_name() === 'cli') {
                echo $error;
            } else {
                error_log($error);
            }
            throw new \RuntimeException('WebSocket 未启用');
        }
    }
} 